package arkham.gui;

import java.awt.Color;
import java.awt.Font;
import java.awt.GraphicsEnvironment;
import java.awt.image.BufferedImage;

import arkham.data.*;
import arkham.data.Board.Location;
import arkham.data.Globals.CommonItemSubtype;
import arkham.data.Globals.DimensionalSymbol;
import arkham.data.Globals.InvestigatorSkill;
import arkham.data.Globals.MonsterAttribute;
import arkham.data.Globals.UniqueItemSubtype;
import arkham.data.Investigator.InvestigatorPower;
import arkham.jaxb.encounter.EventNode;
import arkham.util.AHLogger;
import arkham.util.ImageUtils;
import arkham.util.Pair;
import arkham.util.XmlTools;

import javax.swing.*;
import javax.swing.text.*;

@SuppressWarnings("serial")
public class ArkhamInfoPane extends JTextPane
{
	private StyledDocument styledDoc;
	private Style regular;
	private BufferedImage hand, bloodDrop;
	private Font prestigeFont;
	private StyleContext infoPaneStyleContext;

	public ArkhamInfoPane()
	{
		setEditable(false);
		setFocusable(false);
		setBackground(new Color(235, 235, 235));
		String handIconFile = ResourceSet.getInstance().getIconFilename("Hand");
		hand = ImageUtils.loadImage(handIconFile);
		String bloodIconFile = ResourceSet.getInstance().getIconFilename("Blood Drop");
		bloodDrop = ImageUtils.loadImage(bloodIconFile);
		prestigeFont = ImageUtils.loadFont("fonts/prestige.ttf").deriveFont(
				Font.PLAIN, 14);

		GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
	    ge.registerFont(prestigeFont);
		initStyles();
	}

	/**
	 * Initializes some style constants
	 */
	private void initStyles()
	{
		//Initialize some styles.
		infoPaneStyleContext = new StyleContext();
		styledDoc = new DefaultStyledDocument(infoPaneStyleContext);
		this.setDocument(styledDoc);
		Style def = infoPaneStyleContext.getStyle(StyleContext.DEFAULT_STYLE);

		regular = styledDoc.addStyle("regular", def);
		StyleConstants.setFontFamily(def, "Arial");
		StyleConstants.setFontSize(def, 12);

		Style s = styledDoc.addStyle("italic", regular);
		StyleConstants.setItalic(s, true);

		s = styledDoc.addStyle("bold", regular);
		StyleConstants.setBold(s, true);

		s = styledDoc.addStyle("greyed", regular);
		StyleConstants.setForeground(s, Color.LIGHT_GRAY);

		Style underline = styledDoc.addStyle("underline", regular);
		StyleConstants.setUnderline(underline, true);

		s = styledDoc.addStyle("small", regular);
		StyleConstants.setFontSize(s, 10);

		s = styledDoc.addStyle("medium", regular);
		StyleConstants.setFontSize(s, 14);

		s = styledDoc.addStyle("large", regular);
		StyleConstants.setFontSize(s, 16);

		s = styledDoc.addStyle("title", underline);
		StyleConstants.setAlignment(s, StyleConstants.ALIGN_CENTER);

		s = styledDoc.addStyle("boldtitle", regular);
		StyleConstants.setAlignment(s, StyleConstants.ALIGN_CENTER);
		StyleConstants.setBold(s, true);

		s = styledDoc.addStyle("greyedboldtitle", regular);
        StyleConstants.setAlignment(s, StyleConstants.ALIGN_CENTER);
        StyleConstants.setBold(s, true);
        StyleConstants.setForeground(s, Color.LIGHT_GRAY);

		for (int i = 0; i < XmlTools.SUPPORTED_COLORS.length; i++)
		{
			s = styledDoc.addStyle(XmlTools.SUPPORTED_COLORS[i], regular);
			StyleConstants.setForeground(s, XmlTools.translateColorString(XmlTools.SUPPORTED_COLORS[i]));
		}

		for (int i = 0; i < DimensionalSymbol.values().length; i++)
		{
			s = styledDoc.addStyle(DimensionalSymbol.values()[i].name(), regular);
			StyleConstants.setIcon(s, new ImageIcon(DimensionalSymbol.values()[i].getImage()));
		}

		Style prestige = styledDoc.addStyle("prestige", def);
		StyleConstants.setLineSpacing(prestige, 0.3f);
		StyleConstants.setFontFamily(prestige, prestigeFont.getFamily());
		StyleConstants.setFontSize(prestige, 14);
		Style redblack = styledDoc.addStyle("prestigeRedBlack", prestige);
		StyleConstants.setBackground(redblack, new Color(249, 232, 214));
		StyleConstants.setForeground(redblack, Color.black);
		Style red = styledDoc.addStyle("prestigeRed", redblack);
		StyleConstants.setBackground(red, new Color(249, 232, 214));
		StyleConstants.setForeground(red, new Color(197, 67, 79));
		StyleConstants.setBold(red, true);
		Style blueblack = styledDoc.addStyle("prestigeBlueBlack", prestige);
		StyleConstants.setBackground(blueblack, new Color(221, 226 ,227));
		StyleConstants.setForeground(blueblack, Color.black);
		Style blue = styledDoc.addStyle("prestigeBlue", blueblack);
		StyleConstants.setBackground(blue, new Color(221, 226 ,227));
		StyleConstants.setForeground(blue, new Color(0, 110, 180));
		StyleConstants.setBold(blue, true);

	}

	/**
	 * Gets a copy of the hand icon
	 * @return the hand icon
	 */
	private Icon getHandIcon()
	{
		return new ImageIcon(hand);
	}

	/**
	 * Gets a copy of the blood icon
	 * @return the blood drop icon
	 */
	private Icon getBloodIcon()
	{
		return new ImageIcon(bloodDrop);
	}

	private void clearDocument() throws BadLocationException
	{
		setBackground(new Color(224, 224, 224));
		styledDoc.remove(0, styledDoc.getLength());
		styledDoc.setParagraphAttributes(0, styledDoc.getLength(), regular, true);
		setBorder(null);
	}

	public StyleContext getStyleContext()
	{
		return infoPaneStyleContext;
	}

	/**
	 * Displays information about the specified object
	 * @param o
	 */
	public void displayInfo(Object o)
	{

	}

	/**
	 * Displays information about the ancient one
	 * @param ao the ancient one to display
	 */
	public void displayAncientOne(AncientOne ao)
	{
		if (ao == null)
		{
			return;
		}
		try
		{
			clearDocument();
			styledDoc.insertString(0, ao.getName() + "\n\n", styledDoc.getStyle("bold"));
			styledDoc.insertString(styledDoc.getLength(), "Worshippers\n", styledDoc.getStyle("underline"));
			styledDoc.insertString(styledDoc.getLength(), ao.getWorshipperDesc() + "\n\n", regular);
			styledDoc.insertString(styledDoc.getLength(), ao.getPowerTitle() + "\n", styledDoc.getStyle("underline"));
			styledDoc.insertString(styledDoc.getLength(), ao.getPowerDesc() + "\n\n", regular);
			if (ao.getStartOfBattleDesc() != null && !ao.getStartOfBattleDesc().equals(""))
			{
				styledDoc.insertString(styledDoc.getLength(), "Start of Battle\n", styledDoc.getStyle("underline"));
				styledDoc.insertString(styledDoc.getLength(), ao.getStartOfBattleDesc() + "\n\n", regular);
			}
			styledDoc.insertString(styledDoc.getLength(), "Attack" + "\n", styledDoc.getStyle("underline"));
			styledDoc.insertString(styledDoc.getLength(), ao.getAttackDesc(), regular);
			styledDoc.setParagraphAttributes(0, ao.getName().length(), styledDoc.getStyle("boldtitle"), true);
			setCaretPosition(0);
		}
		catch (BadLocationException e)
		{
			AHLogger.error(e.toString());
		}
	}

	/**
	 * Displays information about an investigator during investigator selection
	 * @param inv the investigator to display
	 */
	public void displayInvestigator(Investigator inv)
	{
		if (inv == null)
		{
			return;
		}
		try
		{
			clearDocument();
			Style bold = styledDoc.getStyle("bold");
			styledDoc.insertString(0, inv.getName() + ", the " + inv.getProfession() + "\n\n", styledDoc.getStyle("bold"));
			styledDoc.insertString(styledDoc.getLength(), "Sanity: ", bold);
			styledDoc.insertString(styledDoc.getLength(), String.valueOf(inv.getMaxSanity()) + "\n",
					styledDoc.getStyle("blue"));
			styledDoc.insertString(styledDoc.getLength(), "Stamina: ", bold);
			styledDoc.insertString(styledDoc.getLength(), String.valueOf(inv.getMaxStamina()) + "\n",
					styledDoc.getStyle("red"));
			styledDoc.insertString(styledDoc.getLength(), "Focus: ", bold);
			styledDoc.insertString(styledDoc.getLength(), String.valueOf(inv.getBaseFocus()) + "\n",
					regular);

			for (int i = 0; i < 6; i++)
			{
				if (i % 2 == 0)
				{
					styledDoc.insertString(styledDoc.getLength(),
							XmlTools.pad(InvestigatorSkill.getSkillName(i), 5) + ": ",
							styledDoc.getStyle("prestigeBlueBlack"));
					for (int j = 0; j <= 3; j++)
					{
						styledDoc.insertString(styledDoc.getLength(),
								String.valueOf(inv.getBaseSkill(i) + j) + " ",
								styledDoc.getStyle("prestigeBlue"));
					}
				}
				else
				{
					styledDoc.insertString(styledDoc.getLength(),
							XmlTools.pad(InvestigatorSkill.getSkillName(i), 5) + ": ",
							styledDoc.getStyle("prestigeRedBlack"));
					for (int j = 0; j <= 3; j++)
					{
						styledDoc.insertString(styledDoc.getLength(),
								String.valueOf(inv.getBaseSkill(i) - j) + " ",
								styledDoc.getStyle("prestigeRed"));
					}
				}
				styledDoc.insertString(styledDoc.getLength(), "\n",
						styledDoc.getStyle("prestigeBlueBlack"));
			}
			styledDoc.insertString(styledDoc.getLength(), "\nHome: ", bold);
			styledDoc.insertString(styledDoc.getLength(), inv.getStartLocation() + "\n", regular);
			styledDoc.insertString(styledDoc.getLength(), "Fixed Possessions: ", bold);
			styledDoc.insertString(styledDoc.getLength(), "$" + inv.getStartMoney(), regular);
			if (inv.getStartClues() > 0)
			{
				styledDoc.insertString(styledDoc.getLength(), ", " + inv.getStartClues() + " Clues",
						regular);
			}
			for (Pair<String, String> pair : inv.getFixedPossessions())
			{
				styledDoc.insertString(styledDoc.getLength(), ", 1 " +
						pair.getB() + " (" + pair.getA() + ")", regular);
			}
			styledDoc.insertString(styledDoc.getLength(), "\n", regular);
			styledDoc.insertString(styledDoc.getLength(), "Random Possessions: ", bold);
			for (int i = 0; i < inv.getRandomPossessions().size(); i++)
			{
				Pair<String, Integer> pair = inv.getRandomPossessions().get(i);
				if (i != 0)
				{
					styledDoc.insertString(styledDoc.getLength(), ", ", regular);
				}
				styledDoc.insertString(styledDoc.getLength(),
						pair.getB() + " " + pair.getA(), regular);
			}
			styledDoc.insertString(styledDoc.getLength(), "\n\n", regular);
			int title2 = styledDoc.getLength();
			styledDoc.insertString(styledDoc.getLength(), "Abilities", regular);
			for (InvestigatorPower pow : inv.getSpecialPowers())
			{
				styledDoc.insertString(styledDoc.getLength(), "\n" + pow.getName() + ": ", bold);
				styledDoc.insertString(styledDoc.getLength(), pow.getDescription(), regular);
			}
			styledDoc.setParagraphAttributes(0, inv.getName().length() +
					inv.getProfession().length() + 6, styledDoc.getStyle("boldtitle"), true);
			styledDoc.setParagraphAttributes(title2, 9, styledDoc.getStyle("boldtitle"), true);
			setCaretPosition(0);
		}
		catch (BadLocationException e)
		{
			AHLogger.error(e.toString());
		}
	}

	/**
	 * Displays info about an investigator card
	 * @param invcard the investigator card
	 */
	public void displayInvestigatorCard(InvestigatorCard invcard)
	{
		if (invcard == null)
		{
			return;
		}
		try
		{
			clearDocument();
			setBackground(invcard.getPreferredColor());
			styledDoc.insertString(0, invcard.getName() + "\n\n", styledDoc.getStyle("bold"));
			if (invcard.getNumCounters() > 0)
			{
				styledDoc.insertString(styledDoc.getLength(), "Tokens: ", styledDoc.getStyle("bold"));
				styledDoc.insertString(styledDoc.getLength(),
						invcard.getNumCounters() + "\n\n", regular);
			}
			if (invcard.isExhausted())
			{
				styledDoc.insertString(styledDoc.getLength(), "Exhausted\n\n", styledDoc.getStyle("bold"));
			}
			String desc = invcard.getDescription();
			int pos = styledDoc.getLength();
			styledDoc.insertString(styledDoc.getLength(), desc + "\n\n", regular);
			int idx = 0;
			while (idx < desc.length())
			{
				int cidx = desc.indexOf(':', idx);
				int nidx = desc.indexOf('\n', idx);

				if (nidx == -1)
				{
					if (cidx != -1)
					{
						styledDoc.setCharacterAttributes(pos + idx, cidx - idx,
								styledDoc.getStyle("bold"), true);
					}
					break;
				}
				if (cidx != -1 && cidx < nidx)
				{
					styledDoc.setCharacterAttributes(pos + idx, cidx - idx,
							styledDoc.getStyle("bold"), true);
				}
				idx = nidx + 1;
			}

			switch (invcard.getType())
			{
			case COMMON:
				CommonItem citem = (CommonItem)invcard;
				styledDoc.insertString(styledDoc.getLength(),
						"Cost: ", styledDoc.getStyle("bold"));
				styledDoc.insertString(styledDoc.getLength(), "$" +
						String.valueOf(citem.getCost()) + "\n", regular);
				if (citem.getSubtype().equals(CommonItemSubtype.PHYS_WEAPON) ||
				        citem.getSubtype().equals(CommonItemSubtype.MAG_WEAPON))
				{
					styledDoc.insertString(styledDoc.getLength(),
							"Hands: ", styledDoc.getStyle("bold"));
					if (citem.getHands() == 0)
					{
						styledDoc.insertString(styledDoc.getLength(), "x", regular);
					}
					else
					{
						for (int i = 0; i < citem.getHands(); i++)
						{
							setCaretPosition(styledDoc.getLength());
							insertIcon(getHandIcon());
						}
					}
				}
				break;
			case UNIQUE:
				UniqueItem uitem = (UniqueItem)invcard;
				styledDoc.insertString(styledDoc.getLength(),
						"Cost: ", styledDoc.getStyle("bold"));
				styledDoc.insertString(styledDoc.getLength(), "$" +
						String.valueOf(uitem.getCost()) + "\n", regular);
				if (uitem.getSubtype().equals(UniqueItemSubtype.PHYS_WEAPON) ||
				        uitem.getSubtype().equals(UniqueItemSubtype.MAG_WEAPON))
				{
					styledDoc.insertString(styledDoc.getLength(),
							"Hands: ", styledDoc.getStyle("bold"));
					if (uitem.getHands() == 0)
					{
						styledDoc.insertString(styledDoc.getLength(), "x", regular);
					}
					else
					{
						for (int i = 0; i < uitem.getHands(); i++)
						{
							setCaretPosition(styledDoc.getLength());
							insertIcon(getHandIcon());
						}
					}
				}
				break;
			case SPELL:
				Spell spell = (Spell)invcard;
				styledDoc.insertString(styledDoc.getLength(),
						"Casting Modifier: ", styledDoc.getStyle("bold"));
				styledDoc.insertString(styledDoc.getLength(),
						XmlTools.getModifier(spell.getCastingModifier()) + "\n", regular);
				styledDoc.insertString(styledDoc.getLength(),
						"Sanity Cost: ", styledDoc.getStyle("bold"));
				styledDoc.insertString(styledDoc.getLength(),
						String.valueOf(spell.getSanityCost()) + "\n", regular);
				if (spell.isCombatSpell())
				{
					styledDoc.insertString(styledDoc.getLength(),
							"Hands: ", styledDoc.getStyle("bold"));
					if (spell.getHands() == 0)
					{
						styledDoc.insertString(styledDoc.getLength(), "x", regular);
					}
					else
					{
						for (int i = 0; i < spell.getHands(); i++)
						{
							setCaretPosition(styledDoc.getLength());
							insertIcon(getHandIcon());
						}
					}
				}
				break;
			}

			styledDoc.setParagraphAttributes(0, invcard.getName().length(), styledDoc.getStyle("boldtitle"), true);
			setCaretPosition(0);
		}
		catch (BadLocationException e)
		{
			AHLogger.error(e.toString());
		}
	}

	/**
	 * Displays information about the investigator power
	 * @param invpower the investigator power to display
	 */
	public void displayInvestigatorPower(InvestigatorPower invpower)
	{
		if (invpower == null)
		{
			return;
		}
		try
		{
			clearDocument();
			styledDoc.insertString(0, invpower.getName() + "\n", styledDoc.getStyle("underline"));
			String desc = invpower.getDescription();
			int pos = styledDoc.getLength();
			int colonIndex = desc.indexOf(':');
			styledDoc.insertString(styledDoc.getLength(), desc, regular);
			if (colonIndex != -1)
			{
				styledDoc.setCharacterAttributes(pos, colonIndex, styledDoc.getStyle("bold"), true);
			}
			styledDoc.setParagraphAttributes(0, invpower.getName().length(), styledDoc.getStyle("title"), true);
			setCaretPosition(0);
		}
		catch (BadLocationException e)
		{
			AHLogger.error(e.toString());
		}
	}

	/**
	 * Displays the info of a location
	 * @param loc the location to display
	 */
	public void displayLocation(Location loc)
	{
		if (loc == null)
		{
			return;
		}
		try
		{
			clearDocument();
			if (loc.isStreet())
			{
				styledDoc.insertString(0, loc.getName() + " Streets\n", styledDoc.getStyle("bold"));
			}
			else
			{
				styledDoc.insertString(0, loc.getName() + "\n", styledDoc.getStyle("bold"));
			}
			if (loc.isSealed())
			{
				styledDoc.insertString(styledDoc.getLength(), "Sealed\n", styledDoc.getStyle("blue"));
			}
			if (loc.isClosed())
			{
				styledDoc.insertString(styledDoc.getLength(), "Closed\n", styledDoc.getStyle("gray"));
			}
			if (loc.isAquatic())
			{
				styledDoc.insertString(styledDoc.getLength(), "Aquatic\n", styledDoc.getStyle("dark orange"));
			}
			if (loc.isStation())
			{
				styledDoc.insertString(styledDoc.getLength(), "Station\n", regular);
			}
			if (loc.getNumClues() > 0)
			{
				styledDoc.insertString(styledDoc.getLength(), loc.getNumClues() + " clues\n",
						styledDoc.getStyle("dark green"));
			}
			if (loc.getGate() != null)
			{
				styledDoc.insertString(styledDoc.getLength(), "Open Gate: ", styledDoc.getStyle("bold"));
				styledDoc.insertString(styledDoc.getLength(), loc.getGate().getName(), regular);
			}
			else if (!loc.isStreet())
			{
				if (loc.getAlternatePower() != null && !loc.getAlternatePower().equals(""))
				{
					styledDoc.insertString(styledDoc.getLength(),
							loc.getAlternatePower() + ": ", styledDoc.getStyle("bold"));
					styledDoc.insertString(styledDoc.getLength(), loc.getAlternateText() + "\n", regular);
				}
				styledDoc.insertString(styledDoc.getLength(), "\nTypical Encounters: ", regular);
				boolean first = true;
				for (String s : loc.getGuaranteedFinds())
				{
					if (!first)
					{
						styledDoc.insertString(styledDoc.getLength(), ", ", regular);
					}
					styledDoc.insertString(styledDoc.getLength(), s, styledDoc.getStyle("bold"));
					first = false;
				}
				for (String s : loc.getCommonFinds())
				{
					if (!first)
					{
						styledDoc.insertString(styledDoc.getLength(), ", ", regular);
					}
					styledDoc.insertString(styledDoc.getLength(), s, regular);
					first = false;
				}
			}
			if (loc.isStreet())
			{
				styledDoc.setParagraphAttributes(0, loc.getName().length() + 8,
						styledDoc.getStyle("boldtitle"), true);
			}
			else
			{
				styledDoc.setParagraphAttributes(0, loc.getName().length(),
						styledDoc.getStyle("boldtitle"), true);
			}
			setCaretPosition(0);
		}
		catch (BadLocationException e)
		{
			AHLogger.error(e.toString());
		}
	}

	/**
	 * Displays the info of a monster
	 * @param mon the monster to display
	 */
	public void displayMonster(Monster mon)
	{
		if (mon == null)
		{
			return;
		}
		try
		{
			clearDocument();
			setBorder(BorderFactory.createCompoundBorder(
					BorderFactory.createLineBorder(mon.getMovement().getColor(), 2),
					BorderFactory.createEmptyBorder(1,1,1,1)));
			styledDoc.insertString(0, mon.getName() + "\n", styledDoc.getStyle("bold"));
			styledDoc.insertString(styledDoc.getLength(), "Awareness: ", styledDoc.getStyle("bold"));
			styledDoc.insertString(styledDoc.getLength(),
					XmlTools.getModifier(mon.getAwareness()) + "\n", regular);
			styledDoc.insertString(styledDoc.getLength(), "Symbol: ", styledDoc.getStyle("bold"));
			styledDoc.insertString(styledDoc.getLength(), " ", styledDoc.getStyle(mon.getSymbol().name()));
			styledDoc.insertString(styledDoc.getLength(), "\n", regular);
			/* Show monster attributes */
			for (MonsterAttribute attrib : mon.getAttributes())
			{
			    styledDoc.insertString(styledDoc.getLength(), attrib.toString() + "\n",
			            styledDoc.getStyle("bold"));
			}
			styledDoc.insertString(styledDoc.getLength(), "\n", regular);
			if (mon.getDescription() != null && !mon.getDescription().equals(""))
			{
				styledDoc.insertString(styledDoc.getLength(), mon.getDescription() + "\n\n", regular);
			}
			if (mon.getFlavorText() != null && !mon.getFlavorText().equals(""))
			{
				styledDoc.insertString(styledDoc.getLength(), mon.getFlavorText() + "\n\n",
						styledDoc.getStyle("italic"));
			}
			styledDoc.insertString(styledDoc.getLength(), "Horror Rating: ", styledDoc.getStyle("bold"));
			if (mon.getHorrorRating() == Monster.NO_HORROR_CHECK_RATING)
			{
				styledDoc.insertString(styledDoc.getLength(), "-\n", styledDoc.getStyle("blue"));
			}
			else
			{
				styledDoc.insertString(styledDoc.getLength(),
						XmlTools.getModifier(mon.getHorrorRating()), styledDoc.getStyle("blue"));
				styledDoc.insertString(styledDoc.getLength(), "\nDamage: ", styledDoc.getStyle("bold"));
				if (mon.getHorrorDamage() == 0)
				{
					styledDoc.insertString(styledDoc.getLength(), "*\n", styledDoc.getStyle("blue"));
				}
				else
				{
					styledDoc.insertString(styledDoc.getLength(),
							String.valueOf(mon.getHorrorDamage()) + "\n", styledDoc.getStyle("blue"));
				}
			}
			styledDoc.insertString(styledDoc.getLength(), "Combat Rating: ", styledDoc.getStyle("bold"));
			if (mon.getCombatRating() == Monster.NO_COMBAT_CHECK_RATING)
			{
				styledDoc.insertString(styledDoc.getLength(), "-\n", styledDoc.getStyle("red"));
			}
			else
			{
				styledDoc.insertString(styledDoc.getLength(),
						XmlTools.getModifier(mon.getCombatRating()), styledDoc.getStyle("red"));
				styledDoc.insertString(styledDoc.getLength(), "\nDamage: ", styledDoc.getStyle("bold"));
				if (mon.getCombatDamage() == 0)
				{
					styledDoc.insertString(styledDoc.getLength(), "*\n", styledDoc.getStyle("red"));
				}
				else
				{
					styledDoc.insertString(styledDoc.getLength(),
							String.valueOf(mon.getCombatDamage() + "\n"), styledDoc.getStyle("red"));
				}
			}
			styledDoc.insertString(styledDoc.getLength(), "Toughness: ", styledDoc.getStyle("bold"));
			for (int i = 0; i < mon.getToughness(); i++)
			{
				setCaretPosition(styledDoc.getLength());
				insertIcon(getBloodIcon());
			}
			styledDoc.setParagraphAttributes(0, mon.getName().length(),
					styledDoc.getStyle("boldtitle"), true);
			setCaretPosition(0);
		}
		catch (BadLocationException e)
		{
			AHLogger.error(e.toString());
		}
	}

	/**
	 * Displays information about a mythos card
	 * @param mythos the mythos card
	 */
	public void displayMythosCard(MythosCard mythos)
	{
		if (mythos == null)
		{
			return;
		}
		try
		{
			clearDocument();
			styledDoc.insertString(0, mythos.getName() + "\n\n", styledDoc.getStyle("bold"));
			styledDoc.insertString(styledDoc.getLength(), mythos.getDescription() + "\n\n", regular);
			styledDoc.insertString(styledDoc.getLength(), "Gate: ", styledDoc.getStyle("bold"));
			if (mythos.getGateLocation() != null)
			{
				styledDoc.insertString(styledDoc.getLength(), mythos.getGateLocation() + "\n", regular);
			}
			else
			{
				styledDoc.insertString(styledDoc.getLength(), "None\n", regular);
			}
			styledDoc.insertString(styledDoc.getLength(), "Clue: ", styledDoc.getStyle("bold"));
			for (int i = 0; i < mythos.getClueLocation().size(); i++)
			{
				if (i != 0) styledDoc.insertString(styledDoc.getLength(), ", ", regular);
				styledDoc.insertString(styledDoc.getLength(), mythos.getClueLocation().get(i), regular);
			}
			if (mythos.getClueLocation().size() == 0)
			{
				styledDoc.insertString(styledDoc.getLength(), "None", regular);
			}
			styledDoc.insertString(styledDoc.getLength(), "\n", regular);
			styledDoc.insertString(styledDoc.getLength(), "Movement:\n", styledDoc.getStyle("bold"));
			styledDoc.insertString(styledDoc.getLength(), mythos.getMovement().longDescription() +
					"\n", regular);
			styledDoc.setParagraphAttributes(0, mythos.getName().length(),
					styledDoc.getStyle("boldtitle"), true);
			setCaretPosition(0);
		}
		catch (BadLocationException e)
		{
			AHLogger.error(e.toString());
		}
	}

	/**
	 * Displays information about a personal effect
	 * @param peff the personal effect to display
	 */
	public void displayPersonalEffect(PersonalEffect peff)
	{
		if (peff == null)
		{
			return;
		}
		try
		{
			clearDocument();
			setBackground(peff.getPreferredColor());
			styledDoc.insertString(0, peff.getName() + "\n", styledDoc.getStyle("bold"));
			String desc = peff.getDescription();
			int pos = styledDoc.getLength();
			styledDoc.insertString(styledDoc.getLength(), desc, regular);
			int idx = 0;
			while (idx < desc.length())
			{
				int cidx = desc.indexOf(':', idx);
				int nidx = desc.indexOf('\n', idx);

				if (nidx == -1)
				{
					if (cidx != -1)
					{
						styledDoc.setCharacterAttributes(pos + idx, cidx - idx,
								styledDoc.getStyle("bold"), true);
					}
					break;
				}
				if (cidx != -1 && cidx < nidx)
				{
					styledDoc.setCharacterAttributes(pos + idx, cidx - idx,
							styledDoc.getStyle("bold"), true);
				}
				idx = nidx + 1;
			}
			styledDoc.setParagraphAttributes(0, peff.getName().length(),
					styledDoc.getStyle("boldtitle"), true);
			setCaretPosition(0);
		}
		catch (BadLocationException e)
		{
			AHLogger.error(e.toString());
		}
	}

	/**
     * Displays the text of an encounter with white background
     * @param locationName the location where the encounter is taking place
     * @param description the description of the encounter
     */
	public void displayEncounter(String locationName, String description)
	{
	    displayEncounter(locationName, description, Color.white);
	}

	/**
	 * Displays the text of an encounter.
	 * @param locationName the location where the encounter is taking place
	 * @param description the description of the encounter
	 * @param bgcolor the background color
	 */
	public void displayEncounter(String locationName, String description, Color bgcolor)
	{
	    if (locationName == null || description == null)
	    {
	        return;
	    }
	    try
        {
            clearDocument();
            setBackground(bgcolor);
            styledDoc.insertString(0, locationName + "\n\n", styledDoc.getStyle("bold"));
            styledDoc.insertString(styledDoc.getLength(), description, regular);
            styledDoc.setParagraphAttributes(0, locationName.length(),
                    styledDoc.getStyle("boldtitle"), true);
            setCaretPosition(0);
        }
        catch (BadLocationException e)
        {
            AHLogger.error(e.toString());
        }
	}

	/**
	 * Displays a gate card. The relevant encounter will be shown in
	 * black and the other encounters would be greyed out.
	 * @param card the gate card
	 * @param owname the name of the other world
	 */
	public void displayGateCard(GateCard card, String owname)
	{
	    if (card == null || owname == null)
        {
            return;
        }
        try
        {
            clearDocument();
            setBackground(card.getGateColor().getBgcolor());
            EventNode node = card.getOtherWorldEncounter(owname);

            styledDoc.insertString(0, node.getLocation() + "\n", styledDoc.getStyle("bold"));
            styledDoc.insertString(styledDoc.getLength(), node.getDescription() + "\n\n", regular);
            styledDoc.setParagraphAttributes(0, node.getLocation().length(),
                    styledDoc.getStyle("boldtitle"), true);
            int pos = styledDoc.getLength();
            for (String loc : card.getLocationSet())
            {
                if (loc == node.getLocation()) continue;
                EventNode node2 = card.getOtherWorldEncounter(loc);
                styledDoc.insertString(styledDoc.getLength(), node2.getLocation() + "\n", regular);
                styledDoc.insertString(styledDoc.getLength(), node2.getDescription() + "\n\n",
                        styledDoc.getStyle("greyed"));
                styledDoc.setParagraphAttributes(pos, node2.getLocation().length(),
                        styledDoc.getStyle("greyedboldtitle"), true);
                pos = styledDoc.getLength();
            }
            setCaretPosition(0);
        }
        catch (BadLocationException e)
        {
            AHLogger.error(e.toString());
        }
	}
}
